﻿using System.Collections.Generic;
using System.Threading;
using System;
using UnityEngine;
public enum SocketState
{
    state_invalid       = 0,    //无连接状态
    state_connect       = 1,    //链接中
    state_connectok     = 2,    //连接OK
};

public enum EvtType
{
    netevt_invalid    = 0,
    netevt_connect    = 1,
    netevt_establish  = 2,
    netevt_fail       = 3,
};

public class SNetEvent
{
    public EvtType eType;
    public int value;

    public SNetEvent()
    {
        eType = EvtType.netevt_invalid;
        value = 0;
    }
};

public class SocketManager
{
    private string      m_szRemoteIP;
    private ushort      m_wPort;
    public        SocketState m_nState = SocketState.state_invalid;
    public        PollIO m_Pollio = null;


    // 事件队列
     private Queue<SNetEvent> m_oEvtQueue = new Queue<SNetEvent>();

     private static SocketManager mInst = null;

    private SocketClientManager socketClientManager = null;
    
     public static SocketManager GetInstance()
    {
        if (mInst == null)
        {
            mInst = new SocketManager();
        }
        return mInst;
    }

    public  void Init(SocketClientManager obj)
    {
        socketClientManager = obj;
    }


    public void ReSetTime()
    {//收到消息
        socketClientManager.ReSetTime();
    }
    public  void OnOpen(string dwIP, ushort wPort)
    {
        if (m_Pollio == null)
            m_Pollio = new PollIO(this);

        mInst.SetRemoteIP(dwIP);
        mInst.SetRemotePort(wPort);
        SetState(SocketState.state_connect);
        // 设置连接事件
        mInst.PushEvent(EvtType.netevt_connect);
    }

    public void OnReConnect()//重连
    {
        if (m_Pollio == null)
            m_Pollio = new PollIO(this);
        SetState(SocketState.state_connect);
        // 设置连接事件
        mInst.PushEvent(EvtType.netevt_connect);
    }


    public  bool Send(GameMsg protocol)
    {
        if (GetState() == SocketState.state_connectok && m_Pollio != null )
        {
            return m_Pollio.Send(protocol);
        }
        return false;
    }

    public bool SendNow(GameMsg protocol)
    {
        if (GetState() == SocketState.state_connectok && m_Pollio != null)
        {
            return m_Pollio.SendNow(protocol);
        }
        return false;
    }

   
    public void Uninit()
    {
        if(m_Pollio != null)
        {
            m_Pollio.UnInit();
            m_Pollio = null;
        }
    }

    private void OnDelSession( )
    {
        Uninit();
        SetState(SocketState.state_invalid);
    }

    private void OnAddSession()
    {
        SetState(SocketState.state_connectok);
        m_Pollio.start();//开启线程
    }

    public void OnConnect()
    {
        if (m_Pollio == null)
            m_Pollio = new PollIO(this);
            m_Pollio.Open(GetRemoteIPStr(), GetRemotePort());
    }

    public void PushEvent(EvtType eType, int value = 0)
    {
        SNetEvent oEvent = new SNetEvent();
        oEvent.eType = eType;
        oEvent.value = value;

        lock (m_oEvtQueue)
        {
            m_oEvtQueue.Enqueue(oEvent);
        }
    }

    public void run()
    {
        //Debug.Log("state:"+GetState()+":"+ SocketState.state_connectok);
        if (m_oEvtQueue.Count < 1 )
        {
            return;
        }

        lock (m_oEvtQueue)
        {
            SNetEvent events = m_oEvtQueue.Dequeue();
            if (events != null)
            {
                switch (events.eType)
                {
                    case EvtType.netevt_connect:
                        {
                            OnConnect();
                        }
                        break;
                    case EvtType.netevt_establish:
                        {
                            OnAddSession();
                        }
                        break;
                    case EvtType.netevt_fail:
                        {
                            OnDelSession();
                        }
                        break;
                    default:
                        break;
                }
            }
        }

        
    }


    public  void SetState(SocketState eState){ m_nState = eState; }
    public  SocketState GetState(){return m_nState; }
    public void  SetRemoteIP(string dwIP){ m_szRemoteIP = dwIP; }
    public  string GetRemoteIPStr() { return m_szRemoteIP; }
    public void SetRemotePort(ushort wPort){ m_wPort = wPort;}
    public ushort GetRemotePort() { return m_wPort; }

}